import itertools
from typing import Any, Callable, List, Tuple, Union, Iterable


class InheritSolverBase:
    def __init__(self, individual_num: int, individual: Callable, **kwargs) -> None:
        """
        Arguments:
         - `individual_num`: 个体数量
         - `individual`: 个体类的构造函数
         - `kwargs`: 个体类的构造函数的参数
        """
        self.group = [individual(**kwargs) for i in range(individual_num)]

    def _filter(self, **kwargs):
        """
        Arguments:
         - `group`: 种群
         - `filter`: 与环境相关的过滤函数，返回值为bool
        """
        raise NotImplementedError

    def _multiply(self, individual: object, **kwargs) -> object:
        """
        Arguments:
         - `group`: 种群
         - `multiply`: 与环境相关的繁殖函数，返回值为新的个体
        """
        raise NotImplementedError

    def _survive(self, **kwargs) -> None:
        """
        自然死亡的
        """
        raise NotImplementedError

    def train(
        self,
        epoch_num: int = 100,
        survive_kwargs: dict = {},
        multiply_kwargs: dict = {},
        filter_kwargs: dict = {},
    ) -> List[object]:
        score = -10000000000
        score_new = 0
        for i in range(epoch_num):
            if i != 0:
                self._survive(**survive_kwargs)
            # 进行一次繁殖，这个函数里面应该包含了变异和自然死亡
            temp_group = list(
                map(
                    lambda x: list(self._multiply(x, **multiply_kwargs)),
                    self.group,
                )
            )
            self.group = list(itertools.chain(*temp_group))
            if i % 5 == 0:
                # 进行一次过滤
                score_new = self._filter(**filter_kwargs)
                if abs(score_new - score) < 1e-10 and i % 100 == 0:
                    break
                score = score_new
        return self.group  # 返回最后一代的种群
